Secrets Manager SQL Connection ドライバーを利用して JDBC で Java アプリケーションから Secrets Manager のローテーションされたパスワードを取得してみた
コーヒーが好きな emi です。
Secrets Manager SQL Connection ドライバーを利用して JDBC で Java アプリケーションから Secrets Manager のローテーションされたパスワードを取得してみました。
私が Java アプリケーション初心者であるため冗長な案内もあるかもしれませんが、お付き合いいただければと思います。
自作サンプルコード
RDS for MySQL からテーブル内容を表示する簡単なサンプルです。Gradle でビルドして使います。
build.gradle
- 25 行目、30 行目周辺をご自身の環境に合わせて変更してください。
src/main/java/com/example/RdsInfoApp.java
- 10、14、32 行目周辺をご自身の環境に合わせて変更してください。
解説
Java アプリケーションでは、Secrets Manager SQL Connection ドライバーを使用して、Secrets Manager に保存されている認証情報を使用して MySQL、PostgreSQL、Oracle、MSSQLServer、Db2、および Redshift データベースに接続できます。各ドライバーはベース JDBC ドライバーをラップしているため、JDBC 呼び出しを使用してデータベースにアクセスすることができます。
ドライバーは Java のクライアント側キャッシュライブラリを使用して認証情報をキャッシュするため、その後の接続では Secrets Manager を呼び出す必要はありません。デフォルトでは 1 時間ごと、およびシークレットがローテーションされたときに、キャッシュが更新されます。
これにより Secrets Manager への API コールを減らすことができ、パフォーマンス向上とコスト削減効果が期待できます。
公式のサンプルコードはこちらです。(自作サンプルコードはこれに気づかずに頑張って作ってしまいました)
検証イメージ図
以下のような構成で検証しました。
- パブリックサブネットの EC2 インスタンス(RHEL9)に、RDS for MySQL のレコードを表示する
.jar
ファイルを配置- Secrets Manager SQL Connection ドライバーを使用して、Secrets Manager に保存されている
username
、password
を取得して RDS for MySQL にアクセス .jar
ファイルを実行して RDS for MySQL に設定済みのage_table
に格納されたレコードを表示
- Secrets Manager SQL Connection ドライバーを使用して、Secrets Manager に保存されている
以下のリソースはあらかじめ作成しておきます。
- EC2
- AMI ID:ami-0014871499315f25a
- AMI 名:RHEL-9.3.0_HVM-20240117-x86_64-49-Hourly2-GP3
- インスタンスタイプ:t3.medium
- t3.micro だとビルド中に高負荷でダウンしてしまいました
- EC2 の IAM ロールには SSM セッションマネージャーを使う権限と、RDS のシークレット ARN に対する
"secretsmanager:GetSecretValue"
、"secretsmanager:DescribeSecret"
を許可する権限を付与
EC2 に付与する IAM ロールに付与する Secrets Manager へのアクセス許可は以下です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:<secrets name>"
}
]
}
- RDS
- エンジン:MySQL Community
- エンジンバージョン:8.0.36
- クラス:db.t3.micro
- 単一の RDS インスタンス
RDS for MySQL の中のデータベースとテーブルが以下のイメージです。
mysql> select * from age_table;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | aoki | 20 |
| 2 | iida | 21 |
| 3 | usui | 22 |
+----+------+------+
3 rows in set (0.01 sec)
mysql>
補足
今回はパブリックサブネットに EC2 インスタンスを配置して実験しましたが、Java アプリケーションを配置するコンピュートサービスがプライベートサブネットに存在する場合は Secrets Manager にアクセスするのに VPC エンドポイントが必要です。Secrets Manager へのアクセス許可する VPC エンドポイントを作成し、VPC エンドポイントに設定するセキュリティグループで EC2 インスタンスからの HTTPS 443 アクセスを許可してください。
事前準備
検証のためのコマンドをインストール(オプション)
EC2 インスタンス(RHEL9)にあらかじめ mysql
コマンドと git
をインストールしておきました。
git バージョン確認コマンド
git --version
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ git --version
git version 2.43.5
[ec2-user@ip-10-0-0-26 ~]$
mysql バージョン確認コマンド
mysql --version
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ mysql --version
mysql Ver 8.0.36 for Linux on x86_64 (Source distribution)
[ec2-user@ip-10-0-0-26 ~]$
RDS for MySQL 内のテーブル準備
あらかじめ RDS for MySQL にデータベースとテーブルを作成しておきました。今回は mysqldb
というデータベースと age_tabel
というテーブルを作成しています。
RDS for MySQL へのログイン(パスワード入力)
mysql -h database-1.xxxxx.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ mysql -h database-1.xxxxx.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 13
Server version: 8.0.36 Source distribution
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
存在するデータベースの確認
show databases;
▼実行結果
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| mysqldb |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.05 sec)
mysql>
データベースの選択
use mysqldb;
▼実行結果
mysql> use mysqldb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql>
mysql> SELECT database();
+------------+
| database() |
+------------+
| mysqldb |
+------------+
1 row in set (0.01 sec)
mysql>
テーブル一覧の表示
show tables;
▼実行結果
mysql> show tables;
+-------------------+
| Tables_in_mysqldb |
+-------------------+
| age_table |
+-------------------+
1 row in set (0.02 sec)
mysql>
DB オブジェクトの定義情報を表示
desc age_table;
▼実行結果
mysql> desc age_table;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(45) | NO | | NULL | |
| age | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.03 sec)
mysql>
age_table;
の表示
select * from age_table;
▼実行結果
mysql> select * from age_table;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | aoki | 20 |
| 2 | iida | 21 |
| 3 | usui | 22 |
+----+------+------+
3 rows in set (0.01 sec)
mysql>
EC2 インスタンス(RHEL9)をアップデートしておきます。
sudo dnf update -y
サンプルコードのクローン
冒頭で案内したサンプルコードを Github から EC2 インスタンス(RHEL9)にクローンしてきます。rds-java-secrets-test
ディレクトリができれば OK です。
git clone git@github.com:emi-ki/rds-java-secrets-test.git
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ git clone git@github.com:emi-ki/rds-java-secrets-test.git
Cloning into 'rds-java-secrets-test'...
Enter passphrase for key '/home/ec2-user/.ssh/id_rsa':
Enter passphrase for key '/home/ec2-user/.ssh/id_rsa':
remote: Enumerating objects: 20, done.
remote: Counting objects: 100% (20/20), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 20 (delta 1), reused 17 (delta 1), pack-reused 0
Receiving objects: 100% (20/20), done.
Resolving deltas: 100% (1/1), done.
[ec2-user@ip-10-0-0-26 ~]$
ls -l
コマンドで rds-java-secrets-test
ディレクトリができているか確認します。
[ec2-user@ip-10-0-0-26 ~]$ ls -l
total 59416
drwxr-xr-x. 3 ec2-user ec2-user 78 Jun 11 18:31 aws
-rw-r--r--. 1 ec2-user ec2-user 60654157 Jun 12 06:37 awscliv2.zip
-rw-r--r--. 1 ec2-user ec2-user 183356 Jun 12 06:58 global-bundle.pem
drwxr-xr-x. 4 ec2-user ec2-user 66 Jul 23 12:09 rds-java-secrets-test
[ec2-user@ip-10-0-0-26 ~]$
ありますね。
では、クローンしてきた .java
ファイルを自分の環境に合わせて修正します。
`src/main/java/com/example/RdsInfoApp.java` の中身
package com.example;
import java.sql.*;
import java.util.Properties;
import com.amazonaws.secretsmanager.sql.AWSSecretsManagerMySQLDriver;
public class RdsInfoApp {
public static void main(String[] args) {
// エンドポイント、ポート、データベース名の設定
String URL = "jdbc-secretsmanager:mysql://database-1.xxxxx.ap-northeast-1.rds.amazonaws.com:3306/<database name>";
// userプロパティにsecret ARNを入力し、secretからユーザーとパスワードを取得
Properties info = new Properties();
info.put("user", "rds!db-xxxxxxxxxxxxxxxxxxxx");
System.out.println("Attempting to connect to: " + URL);
try {
// Secrets Manager SQL Connection JDBC ドライバーをロード
DriverManager.registerDriver(new AWSSecretsManagerMySQLDriver());
// RDS for MySQL への接続
try (Connection connection = DriverManager.getConnection(URL, info)) {
System.out.println("Connection successful!");
// データベースのメタデータを取得
DatabaseMetaData metaData = connection.getMetaData();
System.out.println("Connected as user: " + metaData.getUserName());
// age_table にクエリ
try (Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM age_table")) {
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnsNumber = rsmd.getColumnCount();
System.out.println("age_table の内容:");
// カラム名を出力
for (int i = 1; i <= columnsNumber; i++) {
if (i > 1) System.out.print(" | ");
System.out.print(rsmd.getColumnName(i));
}
System.out.println();
// テーブルの内容を出力
while (resultSet.next()) {
for (int i = 1; i <= columnsNumber; i++) {
if (i > 1) System.out.print(" | ");
System.out.print(resultSet.getString(i));
}
System.out.println();
}
}
}
} catch (SQLException e) {
System.err.println("Error occurred: " + e.getMessage());
e.printStackTrace();
}
}
}
src/main/java/com/example/RdsInfoApp.java
の 10 行目で、自身が作成した RDS for MySQL のエンドポイントと、最初に作成したデータベース名を入れてください。今回はデータベース名 mysqldb
としたので、mysqldb
と入れておきます。
14 行目には RDS のシークレットの名前を入れてください。
build.gradle
の中身も参考に貼っておきます。
`build.gradle` の中身
plugins {
id 'java'
id 'application'
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
repositories {
mavenCentral()
maven {
url "https://aws.oss.sonatype.org/content/repositories/snapshots"
}
}
dependencies {
implementation 'mysql:mysql-connector-java:8.0.33'
implementation 'com.amazonaws.secretsmanager:aws-secretsmanager-jdbc:2.0.2'
implementation 'org.slf4j:slf4j-simple:1.7.32'
}
application {
mainClass = 'com.example.RdsInfoApp' // アプリケーションのエントリポイント
}
jar {
manifest {
attributes 'Main-Class': 'com.example.RdsInfoApp'
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
25 行目 mainClass = 'com.example.RdsInfoApp' // アプリケーションのエントリポイント
と、30 行目 attributes 'Main-Class': 'com.example.RdsInfoApp'
をご自身の環境に合わせて変更してください。
EC2 インスタンスでの Java 実行環境準備
Gradle のインストール
ビルドツールである Gradle をダウンロードするために、wget
コマンドをインストールしておきます。
sudo dnf install wget
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ sudo dnf install wget
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.
Last metadata expiration check: 1:03:54 ago on Tue 23 Jul 2024 11:13:46 AM UTC.
Dependencies resolved.
============================================================================================================================================================================================
Package Architecture Version Repository Size
============================================================================================================================================================================================
Installing:
wget x86_64 1.21.1-7.el9 rhel-9-appstream-rhui-rpms 794 k
Transaction Summary
============================================================================================================================================================================================
Install 1 Package
Total download size: 794 k
Installed size: 3.1 M
Is this ok [y/N]: y
Downloading Packages:
wget-1.21.1-7.el9.x86_64.rpm 14 MB/s | 794 kB 00:00
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 9.4 MB/s | 794 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : wget-1.21.1-7.el9.x86_64 1/1
Running scriptlet: wget-1.21.1-7.el9.x86_64 1/1
Verifying : wget-1.21.1-7.el9.x86_64 1/1
Installed products updated.
Installed:
wget-1.21.1-7.el9.x86_64
Complete!
[ec2-user@ip-10-0-0-26 ~]$
Gradle のどのバージョンをダウンロードするか確認しておきましょう。リリースバージョンは以下のサイトで確認します。
直近で v8.9 がリリースされていました。今回は 1 つ前の v8.8 をダウンロードすることにします。
ダウンロードリンクは以下のサイトで確認します。
gradle-8.8-bin.zip
をダウンロードすればよさそうです。
では Gradle をダウンロードします。
wget https://services.gradle.org/distributions/gradle-8.8-bin.zip
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ wget https://services.gradle.org/distributions/gradle-8.8-bin.zip
--2024-07-23 12:47:25-- https://services.gradle.org/distributions/gradle-8.8-bin.zip
Resolving services.gradle.org (services.gradle.org)... 104.16.73.101, 104.16.72.101, 2606:4700::6810:4965, ...
Connecting to services.gradle.org (services.gradle.org)|104.16.73.101|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://github.com/gradle/gradle-distributions/releases/download/v8.8.0/gradle-8.8-bin.zip [following]
--2024-07-23 12:47:25-- https://github.com/gradle/gradle-distributions/releases/download/v8.8.0/gradle-8.8-bin.zip
Resolving github.com (github.com)... 20.27.177.113
Connecting to github.com (github.com)|20.27.177.113|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/696192900/f26bf10a-b9bc-420a-927d-4eef13716428?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=releaseassetproduction%2F20240723%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240723T124725Z&X-Amz-Expires=300&X-Amz-Signature=4c96f6c6f73a01de14700456b425c74c415bd45f8db9269d9e886b838c923d47&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=696192900&response-content-disposition=attachment%3B%20filename%3Dgradle-8.8-bin.zip&response-content-type=application%2Foctet-stream[following]
--2024-07-23 12:47:26-- https://objects.githubusercontent.com/github-production-release-asset-2e65be/696192900/f26bf10a-b9bc-420a-927d-4eef13716428?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=releaseassetproduction%2F20240723%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240723T124725Z&X-Amz-Expires=300&X-Amz-Signature=4c96f6c6f73a01de14700456b425c74c415bd45f8db9269d9e886b838c923d47&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=696192900&response-content-disposition=attachment%3B%20filename%3Dgradle-8.8-bin.zip&response-content-type=application%2Foctet-stream
Resolving objects.githubusercontent.com (objects.githubusercontent.com)... 185.199.110.133, 185.199.111.133, 185.199.108.133, ...
Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 138039528 (132M) [application/octet-stream]
Saving to: ‘gradle-8.8-bin.zip’
gradle-8.8-bin.zip 100%[====================================================================================================>] 131.64M 109MB/s in 1.2s
2024-07-23 12:47:27 (109 MB/s) - ‘gradle-8.8-bin.zip’ saved [138039528/138039528]
[ec2-user@ip-10-0-0-26 ~]$
[ec2-user@ip-10-0-0-26 ~]$ ls -lh gradle-8.8-bin.zip
-rw-r--r--. 1 ec2-user ec2-user 132M May 31 21:58 gradle-8.8-bin.zip
[ec2-user@ip-10-0-0-26 ~]$
Gradle を解凍するディレクトリを作成します。
sudo mkdir -p /opt/gradle
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ sudo mkdir -p /opt/gradle
[ec2-user@ip-10-0-0-26 ~]$
zip ファイルを解凍します。
sudo unzip -d /opt/gradle ~/gradle-8.8-bin.zip
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ sudo unzip -d /opt/gradle ~/gradle-8.8-bin.zip
Archive: /home/ec2-user/gradle-8.8-bin.zip
creating: /opt/gradle/gradle-8.8/
inflating: /opt/gradle/gradle-8.8/LICENSE
inflating: /opt/gradle/gradle-8.8/NOTICE
inflating: /opt/gradle/gradle-8.8/README
creating: /opt/gradle/gradle-8.8/init.d/
inflating: /opt/gradle/gradle-8.8/init.d/readme.txt
:
:
:
creating: /opt/gradle/gradle-8.8/lib/agents/
inflating: /opt/gradle/gradle-8.8/lib/agents/gradle-instrumentation-agent-8.8.jar
[ec2-user@ip-10-0-0-26 ~]$
以下コマンドで、 Gradle の /opt/gradle/gradle-8.8/bin
(Gradle のバイナリがあるディレクトリ)を PATH
環境変数に追加し、設定を .bashrc
ファイルに保存します。
echo 'export PATH=$PATH:/opt/gradle/gradle-8.8/bin' >> ~/.bashrc
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ echo 'export PATH=$PATH:/opt/gradle/gradle-8.8/bin' >> ~/.bashrc
[ec2-user@ip-10-0-0-26 ~]$
設定を有効にするために、.bashrc
ファイルを再読み込みします。
source ~/.bashrc
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ source ~/.bashrc
[ec2-user@ip-10-0-0-26 ~]$
これで、Gradle コマンドを任意のディレクトリから実行できるようになりました。
OpenJDK 17 のインストール
OpenJDK 17 をインストールします。
sudo dnf install java-17-openjdk-devel
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ sudo dnf install java-17-openjdk-devel
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.
Last metadata expiration check: 1:40:33 ago on Tue 23 Jul 2024 11:13:46 AM UTC.
Dependencies resolved.
============================================================================================================================================================================================
Package Architecture Version Repository Size
============================================================================================================================================================================================
Installing:
java-17-openjdk-devel x86_64 1:17.0.12.0.7-2.el9 rhel-9-appstream-rhui-rpms 4.7 M
Installing dependencies:
ModemManager-glib x86_64 1.20.2-1.el9 rhel-9-baseos-rhui-rpms 337 k
adobe-source-code-pro-fonts noarch 2.030.1.050-12.el9.1 rhel-9-appstream-rhui-rpms 836 k
adwaita-cursor-theme
:
:
:
tracker-miners x86_64 3.1.2-4.el9_3 rhel-9-appstream-rhui-rpms 942 k
xdg-desktop-portal-gtk x86_64 1.12.0-3.el9 rhel-9-appstream-rhui-rpms 139 k
Transaction Summary
============================================================================================================================================================================================
Install 162 Packages
Total download size: 125 M
Installed size: 457 M
Is this ok [y/N]: y
Downloading Packages:
(1/162): copy-jdk-configs-4.0-3.el9.noarch.rpm 562 kB/s | 29 kB 00:00
(2/162): exiv2-libs-0.27.5-2.el9.x86_64.rpm 12 MB/s | 782 kB 00:00
(3/162): gtk-update-icon-cache-3.24.31-2.el9.x86_64.rpm 2.2 MB/s | 37 kB 00:00
(4/162): exiv2-0.27.5-2.el9.x86_64.rpm 12 MB/s | 984 kB 00:00
(5/162): libXcursor-1.2.0-7.el9.x86_64.rpm 1.4 MB/s | 33 kB 00:00
(6/162): libXext-1.3.4-8.el9.x86_64.rpm
:
:
:
xdg-dbus-proxy-0.1.3-1.el9.x86_64 xdg-desktop-portal-1.12.6-1.el9.x86_64 xdg-desktop-portal-gtk-1.12.0-3.el9.x86_64
xkeyboard-config-2.33-2.el9.noarch xml-common-0.6.3-58.el9.noarch xorg-x11-fonts-Type1-7.5-33.el9.noarch
Complete!
[ec2-user@ip-10-0-0-26 ~]$
インストールが完了したら、Java のバージョンを確認します。
java -version
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ java -version
openjdk version "17.0.12" 2024-07-16 LTS
OpenJDK Runtime Environment (Red_Hat-17.0.12.0.7-1) (build 17.0.12+7-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-17.0.12.0.7-1) (build 17.0.12+7-LTS, mixed mode, sharing)
[ec2-user@ip-10-0-0-26 ~]$
JAVA_HOME
が正しく設定されていることを確認します。
echo $JAVA_HOME
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ echo $JAVA_HOME
[ec2-user@ip-10-0-0-26 ~]$
出力が空なので、設定されていないですね。設定していきます。
まず Java のインストールパスを確認します。
sudo update-alternatives --config java
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ sudo update-alternatives --config java
There is 1 program that provides 'java'.
Selection Command
-----------------------------------------------
*+ 1 java-17-openjdk.x86_64 (/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el9.x86_64/bin/java)
Enter to keep the current selection[+], or type selection number:
[ec2-user@ip-10-0-0-26 ~]$
Java 17 のインストールパスが "/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el9.x86_64"
であることが確認できました。このパスを JAVA_HOME
環境変数に設定しましょう。
JAVA_HOME
環境変数として OpenJDK 17 のインストールパスを指定し、~/.bashrc
ファイルに追加します。
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el9.x86_64' >> ~/.bashrc
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el9.x86_64' >> ~/.bashrc
[ec2-user@ip-10-0-0-26 ~]$
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ echo 'export PATH=$PATH:$JAVA_HOME/bin' >> ~/.bashrc
[ec2-user@ip-10-0-0-26 ~]$
変更を反映させるために、以下のコマンドを実行します。
[ec2-user@ip-10-0-0-26 ~]$ source ~/.bashrc
[ec2-user@ip-10-0-0-26 ~]$
これにより、Java の実行ファイルをシステム全体から呼び出せるようになります。
JAVA_HOME
が正しく設定されたか確認します。
[ec2-user@ip-10-0-0-26 ~]$ echo $JAVA_HOME
/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el9.x86_64
[ec2-user@ip-10-0-0-26 ~]$
JAVA_HOME
環境変数に "/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-2.el9.x86_64"
が設定できたことが確認できました。
Java コマンドが JAVA_HOME
から実行されていることを確認します。
$JAVA_HOME/bin/java -version
▼実行結果
[ec2-user@ip-10-0-0-26 ~]$ $JAVA_HOME/bin/java -version
openjdk version "17.0.12" 2024-07-16 LTS
OpenJDK Runtime Environment (Red_Hat-17.0.12.0.7-1) (build 17.0.12+7-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-17.0.12.0.7-1) (build 17.0.12+7-LTS, mixed mode, sharing)
[ec2-user@ip-10-0-0-26 ~]$
JAVA_HOME
から Java が実行できました。
OpenJDK version 17.0.12
の LTS(Long Term Support)バージョンが使用されています。
Red Hat によって提供されているビルドで、64 ビットの Server VM が使用されています。
Gradle が正しく Java を認識しているか確認するため、Gradle のバージョンを確認します。
[ec2-user@ip-10-0-0-26 ~]$ gradle --version
Welcome to Gradle 8.8!
Here are the highlights of this release:
- Running Gradle on Java 22
- Configurable Gradle daemon JVM
- Improved IDE performance for large projects
For more details see https://docs.gradle.org/8.8/release-notes.html
------------------------------------------------------------
Gradle 8.8
------------------------------------------------------------
Build time: 2024-05-31 21:46:56 UTC
Revision: 4bd1b3d3fc3f31db5a26eecb416a165b8cc36082
Kotlin: 1.9.22
Groovy: 3.0.21
Ant: Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM: 17.0.12 (Red Hat, Inc. 17.0.12+7-LTS)
OS: Linux 5.14.0-362.18.1.el9_3.x86_64 amd64
[ec2-user@ip-10-0-0-26 ~]$
Gradle バージョンは 8.8、使用している JVM[1] のバージョンは 17.0.12 (Red Hat, Inc. 17.0.12+7-LTS) であり、インストールした Java のバージョンと一致しています。Gradle が正しくインストールされ、Java 17 を正しく認識していることが確認できました。
プロジェクトのビルドと実行
プロジェクトディレクトリに移動します。
[ec2-user@ip-10-0-0-26 ~]$ cd rds-java-secrets-test/
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$
ドキュメントや公式サンプルでは Maven (pom.xml
) を使っていますが、私の自作サンプルでは Gradle を使っています。
詳細は Maven Central Repository を参照してください。
スニペットは Gradle (short) を使用します。Gradle(short) は Gradle プロジェクトで依存関係を追加する際の簡潔な記法です。
プロジェクトをビルドします。
gradle build --refresh-dependencies
▼実行結果
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$ gradle build --refresh-dependencies
BUILD SUCCESSFUL in 11s
5 actionable tasks: 5 executed
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$
BUILD SUCCESSFUL
と表示され、ビルドが成功しました。
生成された JAR ファイルを確認します
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$ ls -l
total 8
drwxr-xr-x. 8 ec2-user ec2-user 97 Jul 23 16:00 build
-rw-r--r--. 1 ec2-user ec2-user 828 Jul 23 15:59 build.gradle
-rw-r--r--. 1 ec2-user ec2-user 46 Jul 23 12:09 README.md
drwxr-xr-x. 3 ec2-user ec2-user 18 Jul 23 12:09 src
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$ ls -l build
total 0
drwxr-xr-x. 3 ec2-user ec2-user 18 Jul 23 15:59 classes
drwxr-xr-x. 2 ec2-user ec2-user 72 Jul 23 16:00 distributions
drwxr-xr-x. 3 ec2-user ec2-user 21 Jul 23 15:59 generated
drwxr-xr-x. 2 ec2-user ec2-user 39 Jul 23 15:59 libs
drwxr-xr-x. 2 ec2-user ec2-user 68 Jul 23 16:00 scripts
drwxr-xr-x. 5 ec2-user ec2-user 50 Jul 23 15:59 tmp
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$ ls -l build/libs/
total 15160
-rw-r--r--. 1 ec2-user ec2-user 15523380 Jul 23 16:00 rds-java-secrets-test.jar
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$
build/libs/
配下にビルドされた JAR ファイル rds-java-secrets-test.jar
があることが確認できます。
JAR ファイルを実行してアプリケーションをテストします。
JAR ファイルは java -jar build/libs/[生成されたJARファイル名].jar
のように実行します。
java -jar build/libs/rds-java-secrets-test.jar
▼実行結果
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$ java -jar build/libs/rds-java-secrets-test.jar
Attempting to connect to: jdbc-secretsmanager:mysql://database-1.xxxxx.ap-northeast-1.rds.amazonaws.com:3306/mysqldb
Connection successful!
Connected as user: admin@10.0.0.26
age_table の内容:
id | name | age
1 | aoki | 20
2 | iida | 21
3 | usui | 22
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$
RDS for MySQL から age_table
の内容が表示できました。
シークレットをローテーションする
今回私は RDS が自動で作成するマスターユーザーのシークレットで検証したので、RDS 側からシークレット(username
、password
)を変更します。
今回は RDS 側から変更しましたが、別途 MySQL 用ユーザーを作成しパスワードを自動ローテーションさせている場合は Secrets Manager 側の「すぐにシークレットをローテーションさせる」からローテーションさせることができます。
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$ java -jar build/libs/rds-java-secrets-test.jar
Attempting to connect to: jdbc-secretsmanager:mysql://database-1.xxxxx.ap-northeast-1.rds.amazonaws.com:3306/mysqldb
Connection successful!
Connected as user: admin@10.0.0.26
age_table の内容:
id | name | age
1 | aoki | 20
2 | iida | 21
3 | usui | 22
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$
ローテーションしてもちゃんとデータが取れます。再ログインしても大丈夫です。
sh-5.1$ sudo su - ec2-user
Last login: Tue Jul 23 17:26:24 UTC 2024 on pts/2
[ec2-user@ip-10-0-0-26 ~]$
[ec2-user@ip-10-0-0-26 ~]$ cd rds-java-secrets-test/
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$ java -jar build/libs/rds-java-secrets-test.jar
Attempting to connect to: jdbc-secretsmanager:mysql://database-1.xxxxx.ap-northeast-1.rds.amazonaws.com:3306/mysqldb
Connection successful!
Connected as user: admin@10.0.0.26
age_table の内容:
id | name | age
1 | aoki | 20
2 | iida | 21
3 | usui | 22
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$
では RDS に直接ログインして age_table
を変更します。
mysql> INSERT INTO age_table (id, name, age) VALUES (4, 'eguchi', 23);
Query OK, 1 row affected (0.01 sec)
mysql> select * from age_table;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | aoki | 20 |
| 2 | iida | 21 |
| 3 | usui | 22 |
| 4 | eguchi | 23 |
+----+--------+------+
4 rows in set (0.00 sec)
mysql> INSERT INTO age_table (id, name, age) VALUES (5, 'okumura', 24);
Query OK, 1 row affected (0.00 sec)
mysql> select * from age_table;
+----+---------+------+
| id | name | age |
+----+---------+------+
| 1 | aoki | 20 |
| 2 | iida | 21 |
| 3 | usui | 22 |
| 4 | eguchi | 23 |
| 5 | okumura | 24 |
+----+---------+------+
5 rows in set (0.00 sec)
mysql> exit
Bye
sh-5.1$ exit
再度シークレットをローテーションします。
もう一度 EC2 にログインして jar アプリを動かします。
sh-5.1$ sudo su - ec2-user
Last login: Tue Jul 23 18:00:56 UTC 2024 on pts/0
[ec2-user@ip-10-0-0-26 ~]$ cd rds-java-secrets-test/
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$ java -jar build/libs/rds-java-secrets-test.jar
Attempting to connect to: jdbc-secretsmanager:mysql://database-1.xxxxx.ap-northeast-1.rds.amazonaws.com:3306/mysqldb
Connection successful!
Connected as user: admin@10.0.0.26
age_table の内容:
id | name | age
1 | aoki | 20
2 | iida | 21
3 | usui | 22
4 | eguchi | 23
5 | okumura | 24
[ec2-user@ip-10-0-0-26 rds-java-secrets-test]$
データ変更してシークレットをローテーションした後も、ちゃんとレコードが取れました。いいですねぇ。
後でやりたいこと
以下も検証したいと思っています。続報をお待ちください。
- プライベートサブネットの EC2 インスタンスからの実行
- シークレットのキャッシュ更新間隔を変更
参考
Java のプログラムを動かすために必要なソフトウェア。 https://wa3.i-3-i.info/word12706.html ↩︎